//! Party实体相关的数据结构

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Party实体 - 参与方（个人或组织）
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Party {
    pub party_id: String,
    pub party_type_id: String,
    pub external_id: Option<String>,
    pub preferred_currency_uom_id: Option<String>,
    pub description: Option<String>,
    pub status_id: Option<String>,
    pub created_date: Option<DateTime<Utc>>,
    pub created_by_user_login: Option<String>,
    pub last_modified_date: Option<DateTime<Utc>>,
    pub last_modified_by_user_login: Option<String>,
    pub data_source_id: Option<String>,
    pub is_unread: Option<bool>,
}

/// PartyType实体 - 参与方类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PartyType {
    pub party_type_id: String,
    pub parent_type_id: Option<String>,
    pub has_table: Option<bool>,
    pub description: Option<String>,
}

/// Person实体 - 个人信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Person {
    pub party_id: String,
    pub salutation: Option<String>,
    pub first_name: Option<String>,
    pub middle_name: Option<String>,
    pub last_name: Option<String>,
    pub personal_title: Option<String>,
    pub suffix: Option<String>,
    pub nickname: Option<String>,
    pub first_name_local: Option<String>,
    pub middle_name_local: Option<String>,
    pub last_name_local: Option<String>,
    pub other_local: Option<String>,
    pub member_id: Option<String>,
    pub gender: Option<String>,
    pub birth_date: Option<DateTime<Utc>>,
    pub deceased_date: Option<DateTime<Utc>>,
    pub height: Option<f64>,
    pub weight: Option<f64>,
    pub mothers_maiden_name: Option<String>,
    pub marital_status_enum_id: Option<String>,
    pub social_security_number: Option<String>,
    pub passport_number: Option<String>,
    pub passport_expire_date: Option<DateTime<Utc>>,
    pub total_years_work_experience: Option<f64>,
    pub comments: Option<String>,
    pub employment_status_enum_id: Option<String>,
    pub residence_status_enum_id: Option<String>,
    pub occupation: Option<String>,
    pub years_with_employer: Option<i32>,
    pub months_with_employer: Option<i32>,
    pub existing_customer: Option<bool>,
    pub card_id: Option<String>,
}

/// PartyGroup实体 - 组织信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PartyGroup {
    pub party_id: String,
    pub group_name: Option<String>,
    pub group_name_local: Option<String>,
    pub office_site_name: Option<String>,
    pub annual_revenue: Option<f64>,
    pub num_employees: Option<i64>,
    pub ticker_symbol: Option<String>,
    pub comments: Option<String>,
    pub logo_image_url: Option<String>,
}

/// PartyRole实体 - 参与方角色
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PartyRole {
    pub party_id: String,
    pub role_type_id: String,
}

impl PartyRole {
    /// 转换为HashMap用于数据库操作
    pub fn to_data_row(&self) -> HashMap<String, String> {
        let mut data = HashMap::new();
        data.insert("partyId".to_string(), self.party_id.clone());
        data.insert("roleTypeId".to_string(), self.role_type_id.clone());
        data
    }

    /// 从HashMap创建PartyRole实例
    pub fn from_data_row(data: &HashMap<String, String>) -> crate::Result<Self> {
        let party_id = data.get("partyId")
            .ok_or_else(|| Box::new(crate::PartyModError::InvalidData("Missing partyId".to_string())))?
            .clone();
        let role_type_id = data.get("roleTypeId")
            .ok_or_else(|| Box::new(crate::PartyModError::InvalidData("Missing roleTypeId".to_string())))?
            .clone();

        Ok(Self {
            party_id,
            role_type_id,
        })
    }
}

/// RoleType实体 - 角色类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RoleType {
    pub role_type_id: String,
    pub parent_type_id: Option<String>,
    pub has_table: Option<bool>,
    pub description: Option<String>,
}

/// PartyIdentification实体 - 参与方身份标识
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PartyIdentification {
    pub party_id: String,
    pub party_identification_type_id: String,
    pub id_value: String,
}

/// PartyIdentificationType实体 - 身份标识类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PartyIdentificationType {
    pub party_identification_type_id: String,
    pub parent_type_id: Option<String>,
    pub has_table: Option<bool>,
    pub description: Option<String>,
}

impl Party {
    /// 创建新的Party实例
    pub fn new(party_id: String, party_type_id: String) -> Self {
        Self {
            party_id,
            party_type_id,
            external_id: None,
            preferred_currency_uom_id: None,
            description: None,
            status_id: None,
            created_date: Some(Utc::now()),
            created_by_user_login: None,
            last_modified_date: Some(Utc::now()),
            last_modified_by_user_login: None,
            data_source_id: None,
            is_unread: Some(false),
        }
    }

    /// 转换为HashMap用于数据库操作
    pub fn to_data_row(&self) -> HashMap<String, String> {
        let mut data = HashMap::new();
        data.insert("partyId".to_string(), self.party_id.clone());
        data.insert("partyTypeId".to_string(), self.party_type_id.clone());
        
        if let Some(ref external_id) = self.external_id {
            data.insert("externalId".to_string(), external_id.clone());
        }
        if let Some(ref currency) = self.preferred_currency_uom_id {
            data.insert("preferredCurrencyUomId".to_string(), currency.clone());
        }
        if let Some(ref desc) = self.description {
            data.insert("description".to_string(), desc.clone());
        }
        if let Some(ref status) = self.status_id {
            data.insert("statusId".to_string(), status.clone());
        }
        if let Some(created) = self.created_date {
            data.insert("createdDate".to_string(), created.to_rfc3339());
        }
        if let Some(ref user) = self.created_by_user_login {
            data.insert("createdByUserLogin".to_string(), user.clone());
        }
        if let Some(modified) = self.last_modified_date {
            data.insert("lastModifiedDate".to_string(), modified.to_rfc3339());
        }
        if let Some(ref user) = self.last_modified_by_user_login {
            data.insert("lastModifiedByUserLogin".to_string(), user.clone());
        }
        if let Some(ref data_source) = self.data_source_id {
            data.insert("dataSourceId".to_string(), data_source.clone());
        }
        if let Some(unread) = self.is_unread {
            data.insert("isUnread".to_string(), if unread { "Y" } else { "N" }.to_string());
        }
        
        data
    }

    /// 从HashMap创建Party实例
    pub fn from_data_row(data: &HashMap<String, String>) -> crate::Result<Self> {
        let party_id = data.get("partyId")
            .ok_or_else(|| Box::new(crate::PartyModError::InvalidData("Missing partyId".to_string())))?
            .clone();
        let party_type_id = data.get("partyTypeId")
            .ok_or_else(|| Box::new(crate::PartyModError::InvalidData("Missing partyTypeId".to_string())))?
            .clone();

        Ok(Self {
            party_id,
            party_type_id,
            external_id: data.get("externalId").cloned(),
            preferred_currency_uom_id: data.get("preferredCurrencyUomId").cloned(),
            description: data.get("description").cloned(),
            status_id: data.get("statusId").cloned(),
            created_date: data.get("createdDate")
                .and_then(|s| DateTime::parse_from_rfc3339(s).ok())
                .map(|dt| dt.with_timezone(&Utc)),
            created_by_user_login: data.get("createdByUserLogin").cloned(),
            last_modified_date: data.get("lastModifiedDate")
                .and_then(|s| DateTime::parse_from_rfc3339(s).ok())
                .map(|dt| dt.with_timezone(&Utc)),
            last_modified_by_user_login: data.get("lastModifiedByUserLogin").cloned(),
            data_source_id: data.get("dataSourceId").cloned(),
            is_unread: data.get("isUnread").map(|s| s == "Y"),
        })
    }
}

impl Person {
    /// 创建新的Person实例
    pub fn new(party_id: String) -> Self {
        Self {
            party_id,
            salutation: None,
            first_name: None,
            middle_name: None,
            last_name: None,
            personal_title: None,
            suffix: None,
            nickname: None,
            first_name_local: None,
            middle_name_local: None,
            last_name_local: None,
            other_local: None,
            member_id: None,
            gender: None,
            birth_date: None,
            deceased_date: None,
            height: None,
            weight: None,
            mothers_maiden_name: None,
            marital_status_enum_id: None,
            social_security_number: None,
            passport_number: None,
            passport_expire_date: None,
            total_years_work_experience: None,
            comments: None,
            employment_status_enum_id: None,
            residence_status_enum_id: None,
            occupation: None,
            years_with_employer: None,
            months_with_employer: None,
            existing_customer: None,
            card_id: None,
        }
    }

    /// 转换为HashMap用于数据库操作
    pub fn to_data_row(&self) -> HashMap<String, String> {
        let mut data = HashMap::new();
        data.insert("partyId".to_string(), self.party_id.clone());
        
        if let Some(ref salutation) = self.salutation {
            data.insert("salutation".to_string(), salutation.clone());
        }
        if let Some(ref first_name) = self.first_name {
            data.insert("firstName".to_string(), first_name.clone());
        }
        if let Some(ref middle_name) = self.middle_name {
            data.insert("middleName".to_string(), middle_name.clone());
        }
        if let Some(ref last_name) = self.last_name {
            data.insert("lastName".to_string(), last_name.clone());
        }
        if let Some(ref personal_title) = self.personal_title {
            data.insert("personalTitle".to_string(), personal_title.clone());
        }
        if let Some(ref suffix) = self.suffix {
            data.insert("suffix".to_string(), suffix.clone());
        }
        if let Some(ref nickname) = self.nickname {
            data.insert("nickname".to_string(), nickname.clone());
        }
        if let Some(ref first_name_local) = self.first_name_local {
            data.insert("firstNameLocal".to_string(), first_name_local.clone());
        }
        if let Some(ref middle_name_local) = self.middle_name_local {
            data.insert("middleNameLocal".to_string(), middle_name_local.clone());
        }
        if let Some(ref last_name_local) = self.last_name_local {
            data.insert("lastNameLocal".to_string(), last_name_local.clone());
        }
        if let Some(ref other_local) = self.other_local {
            data.insert("otherLocal".to_string(), other_local.clone());
        }
        if let Some(ref member_id) = self.member_id {
            data.insert("memberId".to_string(), member_id.clone());
        }
        if let Some(ref gender) = self.gender {
            data.insert("gender".to_string(), gender.clone());
        }
        if let Some(ref birth_date) = self.birth_date {
            data.insert("birthDate".to_string(), birth_date.to_rfc3339());
        }
        if let Some(ref deceased_date) = self.deceased_date {
            data.insert("deceasedDate".to_string(), deceased_date.to_rfc3339());
        }
        if let Some(height) = self.height {
            data.insert("height".to_string(), height.to_string());
        }
        if let Some(weight) = self.weight {
            data.insert("weight".to_string(), weight.to_string());
        }
        if let Some(ref mothers_maiden_name) = self.mothers_maiden_name {
            data.insert("mothersMaidenName".to_string(), mothers_maiden_name.clone());
        }
        if let Some(ref marital_status_enum_id) = self.marital_status_enum_id {
            data.insert("maritalStatusEnumId".to_string(), marital_status_enum_id.clone());
        }
        if let Some(ref social_security_number) = self.social_security_number {
            data.insert("socialSecurityNumber".to_string(), social_security_number.clone());
        }
        if let Some(ref passport_number) = self.passport_number {
            data.insert("passportNumber".to_string(), passport_number.clone());
        }
        if let Some(ref passport_expire_date) = self.passport_expire_date {
            data.insert("passportExpireDate".to_string(), passport_expire_date.to_rfc3339());
        }
        if let Some(total_years_work_experience) = self.total_years_work_experience {
            data.insert("totalYearsWorkExperience".to_string(), total_years_work_experience.to_string());
        }
        if let Some(ref comments) = self.comments {
            data.insert("comments".to_string(), comments.clone());
        }
        if let Some(ref employment_status_enum_id) = self.employment_status_enum_id {
            data.insert("employmentStatusEnumId".to_string(), employment_status_enum_id.clone());
        }
        if let Some(ref residence_status_enum_id) = self.residence_status_enum_id {
            data.insert("residenceStatusEnumId".to_string(), residence_status_enum_id.clone());
        }
        if let Some(ref occupation) = self.occupation {
            data.insert("occupation".to_string(), occupation.clone());
        }
        if let Some(years_with_employer) = self.years_with_employer {
            data.insert("yearsWithEmployer".to_string(), years_with_employer.to_string());
        }
        if let Some(months_with_employer) = self.months_with_employer {
            data.insert("monthsWithEmployer".to_string(), months_with_employer.to_string());
        }
        if let Some(existing_customer) = self.existing_customer {
            data.insert("existingCustomer".to_string(), if existing_customer { "Y".to_string() } else { "N".to_string() });
        }
        if let Some(ref card_id) = self.card_id {
            data.insert("cardId".to_string(), card_id.clone());
        }
        
        data
    }

    /// 从HashMap创建Person实例
    pub fn from_data_row(data: &HashMap<String, String>) -> crate::Result<Self> {
        let party_id = data.get("partyId")
            .ok_or_else(|| Box::new(crate::PartyModError::InvalidData("Missing partyId".to_string())))?
            .clone();

        Ok(Self {
            party_id,
            salutation: data.get("salutation").cloned(),
            first_name: data.get("firstName").cloned(),
            middle_name: data.get("middleName").cloned(),
            last_name: data.get("lastName").cloned(),
            personal_title: data.get("personalTitle").cloned(),
            suffix: data.get("suffix").cloned(),
            nickname: data.get("nickname").cloned(),
            first_name_local: data.get("firstNameLocal").cloned(),
            middle_name_local: data.get("middleNameLocal").cloned(),
            last_name_local: data.get("lastNameLocal").cloned(),
            other_local: data.get("otherLocal").cloned(),
            member_id: data.get("memberId").cloned(),
            gender: data.get("gender").cloned(),
            birth_date: data.get("birthDate")
                .and_then(|s| DateTime::parse_from_rfc3339(s).ok())
                .map(|dt| dt.with_timezone(&Utc)),
            deceased_date: data.get("deceasedDate")
                .and_then(|s| DateTime::parse_from_rfc3339(s).ok())
                .map(|dt| dt.with_timezone(&Utc)),
            height: data.get("height").and_then(|s| s.parse().ok()),
            weight: data.get("weight").and_then(|s| s.parse().ok()),
            mothers_maiden_name: data.get("mothersMaidenName").cloned(),
            marital_status_enum_id: data.get("maritalStatusEnumId").cloned(),
            social_security_number: data.get("socialSecurityNumber").cloned(),
            passport_number: data.get("passportNumber").cloned(),
            passport_expire_date: data.get("passportExpireDate")
                .and_then(|s| DateTime::parse_from_rfc3339(s).ok())
                .map(|dt| dt.with_timezone(&Utc)),
            total_years_work_experience: data.get("totalYearsWorkExperience").and_then(|s| s.parse().ok()),
            comments: data.get("comments").cloned(),
            employment_status_enum_id: data.get("employmentStatusEnumId").cloned(),
            residence_status_enum_id: data.get("residenceStatusEnumId").cloned(),
            occupation: data.get("occupation").cloned(),
            years_with_employer: data.get("yearsWithEmployer").and_then(|s| s.parse().ok()),
            months_with_employer: data.get("monthsWithEmployer").and_then(|s| s.parse().ok()),
            existing_customer: data.get("existingCustomer").map(|s| s == "Y"),
            card_id: data.get("cardId").cloned(),
        })
    }
}

impl PartyGroup {
    /// 创建新的PartyGroup实例
    pub fn new(party_id: String) -> Self {
        Self {
            party_id,
            group_name: None,
            group_name_local: None,
            office_site_name: None,
            annual_revenue: None,
            num_employees: None,
            ticker_symbol: None,
            comments: None,
            logo_image_url: None,
        }
    }

    /// 转换为HashMap用于数据库操作
    pub fn to_data_row(&self) -> HashMap<String, String> {
        let mut data = HashMap::new();
        data.insert("partyId".to_string(), self.party_id.clone());
        
        if let Some(ref group_name) = self.group_name {
            data.insert("groupName".to_string(), group_name.clone());
        }
        if let Some(ref group_name_local) = self.group_name_local {
            data.insert("groupNameLocal".to_string(), group_name_local.clone());
        }
        if let Some(ref office_site_name) = self.office_site_name {
            data.insert("officeSiteName".to_string(), office_site_name.clone());
        }
        if let Some(annual_revenue) = self.annual_revenue {
            data.insert("annualRevenue".to_string(), annual_revenue.to_string());
        }
        if let Some(num_employees) = self.num_employees {
            data.insert("numEmployees".to_string(), num_employees.to_string());
        }
        if let Some(ref ticker_symbol) = self.ticker_symbol {
            data.insert("tickerSymbol".to_string(), ticker_symbol.clone());
        }
        if let Some(ref comments) = self.comments {
            data.insert("comments".to_string(), comments.clone());
        }
        if let Some(ref logo_image_url) = self.logo_image_url {
            data.insert("logoImageUrl".to_string(), logo_image_url.clone());
        }
        
        data
    }

    /// 从HashMap创建PartyGroup实例
    pub fn from_data_row(data: &HashMap<String, String>) -> crate::Result<Self> {
        let party_id = data.get("partyId")
            .ok_or_else(|| Box::new(crate::PartyModError::InvalidData("Missing partyId".to_string())))?
            .clone();

        Ok(Self {
            party_id,
            group_name: data.get("groupName").cloned(),
            group_name_local: data.get("groupNameLocal").cloned(),
            office_site_name: data.get("officeSiteName").cloned(),
            annual_revenue: data.get("annualRevenue").and_then(|s| s.parse().ok()),
            num_employees: data.get("numEmployees").and_then(|s| s.parse().ok()),
            ticker_symbol: data.get("tickerSymbol").cloned(),
            comments: data.get("comments").cloned(),
            logo_image_url: data.get("logoImageUrl").cloned(),
        })
    }
}